<?php

namespace Wechat;

class WechatApi {
	// 消息类型
	const MSGTYPE_TEXT = 'text'; // 文本消息
	const MSGTYPE_NEWS = 'news'; // 图文消息
	const MSGTYPE_MUSIC = 'music'; // 音乐消息
	
	/**
	 * 接口Token
	 *
	 * @var string
	 */
	private $token;
	
	/**
	 * 从微信服务器接受到的数据
	 *
	 * @var array
	 */
	private $data = array ();
	
	/**
	 * 构造函数
	 *
	 * @param array $configs
	 */
	public function __construct($token) {
		$this->token = $token;
		$this->valid ();
		$this->initData ();
	}
	
	/**
	 * 验证接口
	 */
	private function valid() {
		if (isset ( $_GET ['echostr'] )) {
			$arr = array (
					$this->token,
					$_GET ['timestamp'],
					$_GET ['nonce'] 
			);
			sort ( $arr, SORT_STRING );
			if (sha1 ( implode ( $arr ) ) == $_GET ['signature']) {
				exit ( $_GET ['echostr'] );
			}
			exit ();
		}
	}
	
	/**
	 * 初始化数据
	 */
	private function initData() {
		$postData = $GLOBALS ['HTTP_RAW_POST_DATA'];
		$this->setLog ( $postData );
		$this->data = ( array ) simplexml_load_string ( $postData, 'SimpleXMLElement', LIBXML_NOCDATA );
	}
	
	/**
	 * 记录日志
	 *
	 * @param string $log
	 * @return \Wechat\WechatApi
	 */
	private function setLog($log) {
		// write log
		return $this;
	}
	
	/**
	 * 获取消息数组
	 *
	 * @return array
	 */
	public function getData() {
		return $this->data;
	}
	
	/**
	 * 获取消息发送方账号（OpenID）
	 *
	 * @return string
	 */
	public function getFromUserName() {
		return isset ( $this->data ['FromUserName'] ) ? $this->data ['FromUserName'] : '';
	}
	
	/**
	 * 获取开发者微信号
	 *
	 * @return string
	 */
	public function getToUserName() {
		return isset ( $this->data ['ToUserName'] ) ? $this->data ['ToUserName'] : '';
	}
	
	/**
	 * 消息创建时间
	 *
	 * @return integer
	 */
	public function getCreateTime() {
		return isset ( $this->data ['CreateTime'] ) ? $this->data ['CreateTime'] : 0;
	}
	
	/**
	 * 获取消息类型
	 *
	 * @return string
	 */
	public function getMsgType() {
		return isset ( $this->data ['MsgType'] ) ? $this->data ['MsgType'] : '';
	}
	
	/**
	 * 获取消息ID（64位整型）
	 *
	 * @return integer
	 */
	public function getMsgId() {
		return isset ( $this->data ['MsgId'] ) ? $this->data ['MsgId'] : 0;
	}
	
	/**
	 * 获取多媒体消息媒体ID
	 *
	 * @return integer
	 */
	public function getMediaId() {
		return isset ( $this->data ['MediaId'] ) ? $this->data ['MediaId'] : 0;
	}
	
	/**
	 * 获取消息内容（文本内容，或语音识别的内容）
	 *
	 * @return string
	 */
	public function getContent() {
		if (isset ( $this->data ['Content'] )) {
			return $this->data ['Content'];
		} elseif (isset ( $this->data ['Recognition'] )) {
			return $this->data ['Recognition'];
		}
		return '';
	}
	
	/**
	 * 获取图片消息图片链接
	 *
	 * @return string
	 */
	public function getPicUrl() {
		return isset ( $this->data ['PicUrl'] ) ? $this->data ['PicUrl'] : '';
	}
	
	/**
	 * 获取链接消息数据
	 *
	 * @return array
	 */
	public function getVoiceFormat() {
		return isset ( $this->data ['Format'] ) ? $this->data ['Format'] : '';
	}
	
	/**
	 * 获取图片消息数据
	 * url: 图片地址
	 * mediaid: 图片消息媒体id，可以调用多媒体文件下载接口拉取数据
	 *
	 * @return array
	 */
	public function getImage() {
		return isset ( $this->data ['PicUrl'] ) ? array (
				'url' => $this->data ['PicUrl'],
				'mediaid' => $this->data ['MediaId'] 
		) : array ();
	}
	
	/**
	 * 获取语音消息数据
	 * format: 语音格式，如amr，speex等
	 * mediaid: 语音消息媒体id，可以调用多媒体文件下载接口拉取数据
	 *
	 * @return array
	 */
	public function getVoice() {
		return isset ( $this->data ['Format'] ) ? array (
				'format' => $this->data ['Format'],
				'mediaid' => $this->data ['MediaId'] 
		) : array ();
	}
	
	/**
	 * 获取视频消息数据
	 * mediaid: 语音消息媒体id，可以调用多媒体文件下载接口拉取数据
	 * thumbmediaid: 视频消息缩略图的媒体id，可以调用多媒体文件下载接口拉取数据
	 *
	 * @return array
	 */
	public function getVideo() {
		return isset ( $this->data ['ThumbMediaId'] ) ? array (
				'mediaid' => $this->data ['MediaId'],
				'thumbmediaid' => $this->data ['ThumbMediaId'] 
		) : array ();
	}
	
	/**
	 * 获取链接消息数据
	 * url: 链接地址
	 * title: 链接标题
	 * description: 链接描述
	 *
	 * @return array
	 */
	public function getLink() {
		return isset ( $this->data ['Url'] ) ? array (
				'url' => $this->data ['Url'],
				'title' => $this->data ['Title'],
				'description' => $this->data ['Description'] 
		) : array ();
	}
	
	/**
	 * 获取地理位置数据
	 * x: 地理位置维度
	 * y: 地理位置经度
	 * scale: 地图缩放大小
	 * label: 地理位置信息
	 *
	 * @return array
	 */
	public function getLocation() {
		return isset ( $this->data ['Location_X'] ) ? array (
				'x' => $this->data ['Location_X'],
				'y' => $this->data ['Location_Y'],
				'scale' => $this->data ['Scale'],
				'label' => $this->data ['Label'] 
		) : array ();
	}
	
	/**
	 * 处理XML字符串
	 *
	 * @param string $str
	 * @return string
	 */
	private function handleXmlStr($str) {
		return '<![CDATA[' . preg_replace ( "/[\\x00-\\x08\\x0b-\\x0c\\x0e-\\x1f]/", '', $str ) . ']]>';
	}
	
	/**
	 * 数据XML编码
	 *
	 * @param mixed $data 数据
	 * @return string
	 */
	private function dataToXml($data) {
		$xml = "";
		foreach ( $data as $key => $val ) {
			is_numeric ( $key ) && $key = "item";
			$xml .= "<$key>";
			$xml .= (is_array ( $val ) || is_object ( $val )) ? $this->dataToXml ( $val ) : $this->handleXmlStr ( $val );
			$xml .= "</$key>\n";
		}
		return $xml;
	}
	
	/**
	 * 数据XML编码
	 *
	 * @param mixed $data 数据
	 * @return string
	 */
	private function encodeXml($data) {
		$xml = "<xml>\n";
		$xml .= $this->dataToXml ( $data );
		$xml .= "</xml>";
		return $xml;
	}
	
	/**
	 * 回复文本消息
	 *
	 * @param string $text
	 */
	public function responseText($text) {
		$data = array (
				'ToUserName' => $this->getFromUserName (),
				'FromUserName' => $this->getToUserName (),
				'CreateTime' => time (),
				'MsgType' => self::MSGTYPE_TEXT,
				'Content' => $text 
		);
		$data = $this->encodeXml ( $data );
		echo $data;
	}
	
	/**
	 * 回复图文消息，单单图文
	 *
	 * @param string $title
	 * @param string $description
	 * @param string $picUrl
	 * @param string $url
	 */
	public function responseSingleNews($title, $description, $picUrl, $url) {
		$data = array (
				'ToUserName' => $this->getFromUserName (),
				'FromUserName' => $this->getToUserName (),
				'CreateTime' => time (),
				'MsgType' => self::MSGTYPE_NEWS,
				'ArticleCount' => 1,
				'Articles' => array (
						array (
								'Title' => $title,
								'Description' => $description,
								'PicUrl' => $picUrl,
								'Url' => $url 
						) 
				) 
		);
		$data = $this->encodeXml ( $data );
		echo $data;
	}
	
	/**
	 * 回复图文消息，单图文或多图文
	 * 参数$data结构为：
	 * array(
	 * [0]=>array(
	 * 'Title'=>'title',
	 * 'Description'=>'description',
	 * 'PicUrl'=>'http://www.xxx.com/xxx.jpg',
	 * 'Url'=>'http://www.xxx.com/xxx.html'
	 * ),
	 * [1]=>....
	 * )
	 *
	 * @param array $data
	 */
	public function responseNews($data) {
		$data = array (
				'ToUserName' => $this->getFromUserName (),
				'FromUserName' => $this->getToUserName (),
				'CreateTime' => time (),
				'MsgType' => self::MSGTYPE_NEWS,
				'ArticleCount' => count ( $data ),
				'Articles' => $data 
		);
		$data = $this->encodeXml ( $data );
		echo $data;
	}
	
	/**
	 * 回复音乐消息
	 * 
	 * @param string $title
	 * @param string $description
	 * @param string $musicUrl
	 * @param string $HQMusicUrl
	 */
	public function responseMusic($title, $description, $musicUrl, $HQMusicUrl = null) {
		is_null ( $HQMusicUrl ) && $HQMusicUrl = $musicUrl;
		$data = array (
				'ToUserName' => $this->getFromUserName (),
				'FromUserName' => $this->getToUserName (),
				'CreateTime' => time (),
				'MsgType' => self::MSGTYPE_MUSIC,
				'Music' => array (
						'Title' => $title,
						'Description' => $description,
						'MusicUrl' => $musicUrl,
						'HQMusicUrl' => $HQMusicUrl 
				) 
		);
		$data = $this->encodeXml ( $data );
		echo $data;
	}
}